package com.otitan.forest.right.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.otitan.forest.right.constant.StaticConstant;
import com.otitan.forest.right.dto.BssForestRightInfoEntityDto;
import com.otitan.forest.right.dto.ProgressStatisticsDto;
import com.otitan.forest.right.dto.StatisticsDto;
import com.otitan.forest.right.dto.TreeDto;
import com.otitan.forest.right.entity.*;
import com.otitan.forest.right.enumeration.ReviewStatusEnum;
import com.otitan.forest.right.mapper.BssForestRightInfoMapper;
import com.otitan.forest.right.po.StatisticsPo;
import com.otitan.forest.right.service.BssAuditRecordsService;
import com.otitan.forest.right.service.BssForestRightInfoService;
import com.otitan.forest.right.service.SysInteractiveService;
import com.otitan.forest.right.service.SysOrganizationService;
import com.otitan.forest.right.util.*;
import com.otitan.webapp.framework.basepro.exception.code.BaseResponseCode;
import com.otitan.webapp.framework.basepro.model.DataResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service("bssForestRightInfoService")
public class BssForestRightInfoServiceImpl extends ServiceImpl<BssForestRightInfoMapper, BssForestRightInfoEntity> implements BssForestRightInfoService {

    @Autowired
    private BssAuditRecordsService bssAuditRecordsService;

    @Autowired
    private BssForestRightInfoMapper bssForestRightInfoMapper;

    @Autowired
    private SysInteractiveService sysInteractiveService;

//    @Autowired
//    private BssForestRightInfoProducers producers;

    @Autowired
    private SysOrganizationService sysOrganizationService;


    @Value("${forest-right.file.excel-folder}")
    private String excelFolder;

    @Value("${forest-right.file.mdb-or-zip-folder}")
    private String mdbOrZipFolder;

    @Value("${forest-right.file.error-folder}")
    private String errorFolder;

    @Value("${forest-right.exe.path}")
    private String exePath;

    @Override
    public DataResult add(BssForestRightInfoEntity bssForestRightInfo) {

//        if (StrUtil.isBlank(bssForestRightInfo.getGroundNo())) {
           /* Map<String, String> map = new HashMap<>();
            map.put("groundNo", bssForestRightInfo.getGroundNo());
            Long count = bssForestRightInfoMapper.findCountByGroundNo(map);
            if (count > 0) {
                return DataResult.fail("宗地号不能重复");
            }*/
//            return DataResult.fail("宗地号不能为空");
//        }

        bssForestRightInfo.setHaveGis(StaticConstant.NOT_HAVE_GIS);
        SysUserEntity sysUserEntity = (SysUserEntity) SecurityUtils.getSubject().getPrincipal();

        // 县级
        if (StrUtil.isBlank(bssForestRightInfo.getCounty())) {
            bssForestRightInfo.setCounty(sysUserEntity.getCounty());
        }
        // 市级
        if (StrUtil.isBlank(bssForestRightInfo.getCity())) {
            bssForestRightInfo.setCity(sysUserEntity.getCity());
        }
        // 省级
        if (StrUtil.isBlank(bssForestRightInfo.getProvince())) {
            bssForestRightInfo.setProvince(sysUserEntity.getProvince());
        }


        boolean save = this.save(bssForestRightInfo);
        // 保存操作记录
        BssAuditRecordsEntity auditRecordsEntity = new BssAuditRecordsEntity();
        auditRecordsEntity.setForestRightId(bssForestRightInfo.getId());
        auditRecordsEntity.setStatus(bssForestRightInfo.getStatus());
        bssAuditRecordsService.save(auditRecordsEntity);

        if (save) {
//             加入队列
//            producers.send(JSONObject.toJSONString(bssForestRightInfo));
            log.debug("\ns 图形文件路径{}", bssForestRightInfo.getFilePath());
            if (StrUtil.isNotBlank(bssForestRightInfo.getFilePath())) {
                String uuid = UUID.randomUUID().toString();
                SysInteractiveEntity interactiveEntity = new SysInteractiveEntity();
                interactiveEntity.setId(getMaxId());
                interactiveEntity.setGuid(uuid);
                interactiveEntity.setStates(StaticConstant.HAS_NOT_STARTED);
                sysInteractiveService.save(interactiveEntity);
                // 调用外部程序
                CellOtherProgram exeUtil = new CellOtherProgram(
                        exePath,
                        bssForestRightInfo.getFilePath(),
                        sysUserEntity.getId(),
                        bssForestRightInfo.getId(),
                        sysUserEntity.getProvince(),
                        sysUserEntity.getCity(),
                        sysUserEntity.getCounty(),
                        uuid
                );
                exeUtil.send();

                return getResDataByGuid(uuid);
            } else {
                return DataResult.success();
            }
        }
        return DataResult.fail(BaseResponseCode.SYSTEM_BUSY.getMsg());
    }

    private DataResult getResDataByGuid(String guid) {
        Page page = new Page(0, 1);
        LambdaQueryWrapper<SysInteractiveEntity> queryWrapper = Wrappers.lambdaQuery();
        //查询条件示例
        queryWrapper.orderByDesc(SysInteractiveEntity::getId);
        queryWrapper.eq(SysInteractiveEntity::getGuid, guid);
        IPage<SysInteractiveEntity> iPage = sysInteractiveService.page(page, queryWrapper);
        List<SysInteractiveEntity> records = iPage.getRecords();

        if (CollUtil.isNotEmpty(records)) {
            SysInteractiveEntity interactiveEntity = records.get(0);

            if ("2".equals(interactiveEntity.getStates())) {
                return DataResult.fail(interactiveEntity.getBz());
            } else if ("3".equals(interactiveEntity.getStates())) {
                return DataResult.fail("质检不通过");
            } else if ("1".equals(interactiveEntity.getStates())) {
                return DataResult.success();
            } else if ("0".equals(interactiveEntity.getStates())) {
                return DataResult.fail("图形关联失败");
            }
        }
        return DataResult.fail(BaseResponseCode.SYSTEM_BUSY.getMsg());
    }

    private Integer getMaxId() {
        Page page = new Page(0, 1);
        LambdaQueryWrapper<SysInteractiveEntity> queryWrapper = Wrappers.lambdaQuery();
        //查询条件示例
        queryWrapper.orderByDesc(SysInteractiveEntity::getId);
        IPage<SysInteractiveEntity> iPage = sysInteractiveService.page(page, queryWrapper);
        List<SysInteractiveEntity> records = iPage.getRecords();

        if (CollUtil.isNotEmpty(records)) {
            Integer id = records.get(0).getId();
            return ++id;
        }
        return 1;

    }

    @Override
    public DataResult dealWith(BssAuditRecordsEntity entity) {

        BssForestRightInfoEntity bssForestRightInfoEntity =
                getById(entity.getForestRightId());
        Integer status = entity.getStatus();

        // 设置状态
        bssForestRightInfoEntity.setStatus(status);

        // 修改林权证数据
        updateById(bssForestRightInfoEntity);

        // 加入队列
//        producers.send(JSONObject.toJSONString(bssForestRightInfoEntity));

        // 保存操作记录
        bssAuditRecordsService.save(entity);
        return DataResult.success();
    }

    @Override
    public List<BssForestRightInfoEntity> findItemsByIds(List<String> ids) {
        return bssForestRightInfoMapper.findItemsByIds(ids);
    }


    /**
     * 构建查询条件
     *
     * @return void
     * @throws
     * @author jiachangsen
     * @date 2020/08/07 16:53
     */
    private boolean buildQueryWrapper(BssForestRightInfoEntity entity, LambdaQueryWrapper<BssForestRightInfoEntity> queryWrapper) {
        boolean flag = false;
        queryWrapper.orderByDesc(BssForestRightInfoEntity::getCreateDate);
        // 林权证号
        if (StringUtils.isNotBlank(entity.getForestRightNo())) {
            queryWrapper.like(BssForestRightInfoEntity::getForestRightNo, entity.getForestRightNo());
        }
        // 宗地号
        if (StringUtils.isNotBlank(entity.getGroundNo())) {
            queryWrapper.like(BssForestRightInfoEntity::getGroundNo, entity.getGroundNo());
        }
        // 林地所有权权利人
        if (StringUtils.isNotBlank(entity.getLandBelongUser())) {
            queryWrapper.like(BssForestRightInfoEntity::getLandBelongUser, entity.getLandBelongUser());
        }
        // 林地承包经营权权利人
        if (StringUtils.isNotBlank(entity.getLandManageUser())) {
            queryWrapper.like(BssForestRightInfoEntity::getLandManageUser, entity.getLandManageUser());
        }
        // 林地使用权（自留山）权利人
        if (StringUtils.isNotBlank(entity.getLandUseUser())) {
            queryWrapper.like(BssForestRightInfoEntity::getLandUseUser, entity.getLandUseUser());
        }
        // 林木所有权权利人
        if (StringUtils.isNotBlank(entity.getTreesBelongUser())) {
            queryWrapper.like(BssForestRightInfoEntity::getTreesBelongUser, entity.getTreesBelongUser());
        }
        // 林木使用权权利人
        if (StringUtils.isNotBlank(entity.getTreesUseUser())) {
            queryWrapper.like(BssForestRightInfoEntity::getTreesUseUser, entity.getTreesUseUser());
        }
        // 状态
        if (entity.getStatus() != null) {
            queryWrapper.eq(BssForestRightInfoEntity::getStatus, entity.getStatus());
        }

        //是否关联图形，（0 未关联，1 已关联）
        if (StringUtils.isNotBlank(entity.getHaveGis())) {
            queryWrapper.eq(BssForestRightInfoEntity::getHaveGis, entity.getHaveGis());
        }

        //乡/镇/街道
        if (StringUtils.isNotBlank(entity.getTown())) {
            queryWrapper.like(BssForestRightInfoEntity::getTown, entity.getTown());
        }

        //市
        if (StringUtils.isNotBlank(entity.getCity())) {
            queryWrapper.like(BssForestRightInfoEntity::getCity, entity.getCity());
        }

        //县
        if (StringUtils.isNotBlank(entity.getCounty())) {
            queryWrapper.like(BssForestRightInfoEntity::getCounty, entity.getCounty());
        }


        // 获取当前登录用户信息
        SysUserEntity sysUserEntity = (SysUserEntity) SecurityUtils.getSubject().getPrincipal();

        // 组织机构
        String groupId = null;
        String userId = null;

        // 所属机构层级  1.省  2.市  3.县
        Integer belongGroupLevel = null;
        if (sysUserEntity != null) {
            userId = sysUserEntity.getId();
            belongGroupLevel = sysUserEntity.getBelongGroupLevel();
        } else {
            log.error("【获取当前登录用户信息失败】：{}", sysUserEntity);
            flag = true;
        }

        switch (belongGroupLevel) {
            case 3:
                // 县级 查看所有状态数据
//                queryWrapper.eq(BssForestRightInfoEntity::getCreateUser, userId);
                queryWrapper.eq(BssForestRightInfoEntity::getCounty, sysUserEntity.getCounty());
                break;
            case 2:
                // 市级 查看除 待提交 状态数据
                queryWrapper.eq(BssForestRightInfoEntity::getCity, sysUserEntity.getCity());
                queryWrapper.in(BssForestRightInfoEntity::getStatus, 1, 2, 3, 4, 5);
                break;
            case 1:
                // 省级 查看除 待提交、待审核、市级退回 状态数据
                queryWrapper.eq(BssForestRightInfoEntity::getProvince, sysUserEntity.getProvince());
                queryWrapper.in(BssForestRightInfoEntity::getStatus, 2, 3, 4);
                break;
            default:
                break;
        }
        return flag;
    }

    @Override
    public DataResult findListByPage(BssForestRightInfoEntity entity) {
        Page page = new Page(entity.getPage(), entity.getSize());
        LambdaQueryWrapper<BssForestRightInfoEntity> queryWrapper = Wrappers.lambdaQuery();

        // 构建查询条件
        boolean flag = this.buildQueryWrapper(entity, queryWrapper);
        if (flag) {
            return DataResult.fail("登录超时，请重新登录系统");
        }
        IPage<BssForestRightInfoEntity> iPage = this.page(page, queryWrapper);
        return DataResult.success(iPage);
    }

    @Override
    public List<BssAuditRecordsEntity> findRecordsById(String id) {
        return bssForestRightInfoMapper.findRecordsById(id);
    }

    @Override
    public void exportZip(BssForestRightInfoEntity entity, HttpServletResponse response) {
        if (StrUtil.isEmpty(entity.getTown())) {
            DataResult.fail("请选择具体的乡镇导出。");
        }

        LambdaQueryWrapper<BssForestRightInfoEntity> queryWrapper = Wrappers.lambdaQuery();
        // 构建查询条件
        BssForestRightInfoEntity entity1 = new BssForestRightInfoEntity();
        entity1.setTown(entity.getTown());
        boolean flag = this.buildQueryWrapper(entity1, queryWrapper);
        if (flag) {
            DataResult.fail("登录超时，请重新登录系统");
        }

        List<BssForestRightInfoEntity> bssForestRightInfoEntityList = this.list(queryWrapper);

        List<SysOrganizationEntity> sysOrganizationEntityList = bssForestRightInfoMapper.findOrganzationList();
        Map<String, String> map = sysOrganizationEntityList.stream()
                .collect(Collectors.toMap(SysOrganizationEntity::getId, SysOrganizationEntity::getName));
        List<BssForestRightInfoEntityDto> list = new ArrayList<>();


        for (BssForestRightInfoEntity bssForestRightInfoEntity : bssForestRightInfoEntityList) {
            BssForestRightInfoEntityDto dto = new BssForestRightInfoEntityDto();
            BeanUtils.copyProperties(bssForestRightInfoEntity, dto);
            dto.setCity(map.get(dto.getCity()));
            dto.setProvince(map.get(dto.getProvince()));
            dto.setCounty(map.get(dto.getCounty()));
            dto.setTown(map.get(dto.getTown()));
            String name = ReviewStatusEnum.getName(dto.getStatus());
            dto.setStatusToString(name);
            list.add(dto);
        }

        String zipFileName = "";
        if (CollUtil.isNotEmpty(list)) {
            BssForestRightInfoEntityDto dto = list.get(0);
            zipFileName = "【" + dto.getCounty() + "-" + dto.getTown() + "】";
        }
        Map<String, List<BssForestRightInfoEntityDto>> collect = list.stream()
                .collect(Collectors.groupingBy(item -> {
                    if (StrUtil.isEmpty(item.getVillage())) {
                        return "";
                    }
                    return item.getVillage();
                }));

        List<String> filePaths = new ArrayList<>();
        // 按照村保存Excel文件
        for (List<BssForestRightInfoEntityDto> value : collect.values()) {
            String filePath = MyExcelUtil.saveExcelFile(excelFolder, value);
            if (StrUtil.isNotEmpty(filePath)) {
                filePaths.add(filePath);
            }
        }
        // 创建压缩文件，并下载
        MyExcelUtil.mackZipAndDownload(response, filePaths, zipFileName);
    }

    @Override
    public void exportMdb(HttpServletResponse response, BssForestRightInfoEntity bssForestRightInfoEntity) {
        String filePath = "E:\\demo\\66.txt";
        FileUtil.exportMdb(response, filePath);
    }

    @Override
    public DataResult uploadMdb(MultipartFile file) {
        if (file.isEmpty()) {
            return DataResult.fail("上传失败，请选择文件");
        }
        // 保存文件
        String fileNewPath = CommonUtil.uploadMdb(mdbOrZipFolder, file);

        Map<String, String> resMap = new HashMap<>();
        resMap.put("filePath", fileNewPath);
        return DataResult.success(resMap);
    }

    @Override
    public void download(BssForestRightInfoEntity entity, HttpServletResponse httpServletResponse) throws IOException {
        List<SysOrganizationEntity> sysOrganizationEntityList = bssForestRightInfoMapper.findOrganzationList();
        Map<String, String> map = new HashMap<>();

        for (SysOrganizationEntity sysOrganizationEntity : sysOrganizationEntityList) {
            map.put(sysOrganizationEntity.getId(), sysOrganizationEntity.getName());
        }

        LambdaQueryWrapper<BssForestRightInfoEntity> queryWrapper = Wrappers.lambdaQuery();
        // 构建查询条件
        boolean flag = this.buildQueryWrapper(entity, queryWrapper);
        if (flag) {
            DataResult.fail("登录超时，请重新登录系统");
        }

        List<BssForestRightInfoEntity> bssForestRightInfoEntityList = this.list(queryWrapper);

        List<BssForestRightInfoEntityDto> list = new ArrayList<>();

        for (BssForestRightInfoEntity bssForestRightInfoEntity : bssForestRightInfoEntityList) {
            BssForestRightInfoEntityDto dto = new BssForestRightInfoEntityDto();

            BeanUtils.copyProperties(bssForestRightInfoEntity, dto);

            dto.setCity(map.get(dto.getCity()));
            dto.setProvince(map.get(dto.getProvince()));
            dto.setCounty(map.get(dto.getCounty()));
            dto.setTown(map.get(dto.getTown()));
           /* dto.setVillage(map.get(dto.getVillage()));
            dto.setGroupName(map.get(dto.getGroupName()));*/
            String name = ReviewStatusEnum.getName(dto.getStatus());
            dto.setStatusToString(name);
            list.add(dto);


        }

        InputStream inp = ExcelUtil.class.getResourceAsStream("/excel/【导出模板】贵州省林权登记信息入库数字化表.xlsx");
        XSSFWorkbook wb = new XSSFWorkbook(inp);
        SXSSFWorkbook swb = new SXSSFWorkbook(wb, -1);
        XSSFWorkbook xssfWorkbook = swb.getXSSFWorkbook();
        XSSFSheet sheet = xssfWorkbook.getSheetAt(0);

        XSSFCellStyle cellStyle = FileUtil.setCellStyle(xssfWorkbook);

        FileUtil.setCellStyleAndValue(list, sheet, cellStyle);

        String fileName = "贵州省林权登记信息入库数字化表-" + DateUtil.getNowDateStr() + ".xlsx";
        FileUtil.exportExcelByDownload(xssfWorkbook, httpServletResponse, fileName);

    }

    @Override
    public DataResult progressStatistics(StatisticsDto dto) {
        log.debug("查询参数dto{}", dto);
        // 根据年份获取统计时间段
        Map<String, Object> dateMap = getStartDateAndEndDate(dto.getYear());
        if (StrUtil.isNotEmpty(dto.getCity())) {
            dateMap.put("city", dto.getCity());
        }
        if (StrUtil.isNotEmpty(dto.getCounty())) {
            dateMap.put("county", dto.getCounty());
        }
        if (StrUtil.isNotEmpty(dto.getTown())) {
            dateMap.put("town", dto.getTown());
        }

        // 获取当前登录用户信息
        SysUserEntity sysUserEntity = (SysUserEntity) SecurityUtils.getSubject().getPrincipal();

        // 组织机构
        String groupId = null;

        // 所属机构层级  1.省  2.市  3.县
        Integer belongGroupLevel = null;
        if (sysUserEntity != null) {
            groupId = sysUserEntity.getGroupId();
            belongGroupLevel = sysUserEntity.getBelongGroupLevel();
        } else {
            return DataResult.fail("登录超时，请重新登录系统");
        }

        switch (belongGroupLevel) {
            case 3:
                // 县级
                dateMap.put("county", groupId);
//                dateMap.put("createUser", sysUserEntity.getId());
                break;
            case 2:
                // 市级
                dateMap.put("city", groupId);
                break;
            case 1:
                // 省级
                dateMap.put("province", groupId);
                break;
            default:
                break;
        }
        log.debug("查询参数dateMap{}", dateMap);
        // 入库总本数、总面积
        List<StatisticsPo> totalNumAndTotalAreaDb =
                bssForestRightInfoMapper.findTotalNumAndTotalArea(dateMap);
        // 入库宗地数
        List<StatisticsPo> totalGroundNumDb =
                bssForestRightInfoMapper.findTotalGroundNum(dateMap);

        dateMap.put("status", ReviewStatusEnum.EXAMINATION_PASSED.getCode());
        // 发证总本数、总面积
        List<StatisticsPo> totalNumAndTotalArea =
                bssForestRightInfoMapper.findTotalNumAndTotalArea(dateMap);
        // 发证宗地数
        List<StatisticsPo> totalGroundNum =
                bssForestRightInfoMapper.findTotalGroundNum(dateMap);


        return DataResult.success(processingStatistics(dto.getYear(), totalNumAndTotalAreaDb,
                totalGroundNumDb, totalNumAndTotalArea, totalGroundNum));
    }

    /**
     * 处理统计数据
     *
     * @param [year, totalNumAndTotalAreaDb, totalGroundNumDb, totalNumAndTotalArea, totalGroundNum]
     * @throws
     * @author jiachangsen
     * @date 2020/08/13 08:50
     */
    private Map<String, Object> processingStatistics(
            String year,
            List<StatisticsPo> totalNumAndTotalAreaDb,
            List<StatisticsPo> totalGroundNumDb,
            List<StatisticsPo> totalNumAndTotalArea,
            List<StatisticsPo> totalGroundNum) {
        String[] months = null;
        if ("2020".equals(year)) {
            months = DateUtil.MONTHS_2020;
        } else {
            months = DateUtil.MONTHS;
        }
        // 发证总本书
        List<BigDecimal> licensedBook = new ArrayList<>();
        // 入库总本书
        List<BigDecimal> licensedBookDb = new ArrayList<>();
        // 发证总本书占比
        List<BigDecimal> licensedBookPercentage = new ArrayList<>();

        // 发证总面积
        List<BigDecimal> licensedArea = new ArrayList<>();
        // 入库总面积
        List<BigDecimal> licensedAreaDb = new ArrayList<>();
        // 发证总面积占比
        List<BigDecimal> licensedAreaPercentage = new ArrayList<>();

        // 发证总宗地数
        List<BigDecimal> licensedGround = new ArrayList<>();
        // 入库总宗地数
        List<BigDecimal> licensedGroundDb = new ArrayList<>();
        // 发证总宗地数占比
        List<BigDecimal> licensedGroundPercentage = new ArrayList<>();

        for (String month : months) {
            // 入库总本数、总面积
            boolean flag = true;
            setValues(month, flag, totalNumAndTotalAreaDb, licensedBookDb, licensedAreaDb);

            // 发证总本数、总面积
            flag = true;
            setValues(month, flag, totalNumAndTotalArea, licensedBook, licensedArea);

            // 入库宗地数
            flag = true;
            setValues(month, flag, totalGroundNumDb, licensedGroundDb, null);

            // 发证宗地数
            flag = true;
            setValues(month, flag, totalGroundNum, licensedGround, null);

        }
        BigDecimal decimal0 = BigDecimal.valueOf(0);
        BigDecimal decimal100 = BigDecimal.valueOf(100);
        DecimalFormat df = new DecimalFormat("#0.00");
        for (int i = 0; i < months.length; i++) {
            if (!decimal0.equals(licensedBookDb.get(i))) {
                BigDecimal divide = licensedBook.get(i)
                        .divide(licensedBookDb.get(i), 4, BigDecimal.ROUND_HALF_UP)
                        .multiply(decimal100)
                        .setScale(2, BigDecimal.ROUND_HALF_UP);
                licensedBookPercentage.add(divide);
            } else {
                licensedBookPercentage.add(decimal0);
            }
            if (!decimal0.equals(licensedAreaDb.get(i))) {
                BigDecimal divide1 = licensedArea.get(i)
                        .divide(licensedAreaDb.get(i), 4, BigDecimal.ROUND_HALF_UP)
                        .multiply(decimal100)
                        .setScale(2, BigDecimal.ROUND_HALF_UP);
                licensedAreaPercentage.add(divide1);
            } else {
                licensedAreaPercentage.add(decimal0);
            }
            if (!decimal0.equals(licensedGroundDb.get(i))) {
                BigDecimal divide2 = licensedGround.get(i)
                        .divide(licensedGroundDb.get(i), 4, BigDecimal.ROUND_HALF_UP)
                        .multiply(decimal100)
                        .setScale(2, BigDecimal.ROUND_HALF_UP);
                licensedGroundPercentage.add(divide2);
            } else {
                licensedGroundPercentage.add(decimal0);
            }
        }

        long totalNumberOfCertificates =
                licensedBook.stream().mapToLong(BigDecimal::intValue).sum();
        double totalAreaOfIssuance =
                licensedArea.stream().mapToDouble(BigDecimal::doubleValue).sum();
        long licensedTotalParcel =
                licensedGround.stream().mapToLong(BigDecimal::intValue).sum();

        ProgressStatisticsDto dto =
                new ProgressStatisticsDto(
                        BigDecimal.valueOf(totalNumberOfCertificates),
                        BigDecimal.valueOf(totalAreaOfIssuance),
                        BigDecimal.valueOf(licensedTotalParcel),
                        licensedBookDb,
                        licensedBookPercentage,
                        licensedAreaDb,
                        licensedAreaPercentage,
                        licensedGroundDb,
                        licensedGroundPercentage
                );
        Map<String, Object> resMap = new HashMap<>();
        resMap.put("months", months);
        resMap.put("data", dto);
        return resMap;
    }

    @Override
    public DataResult batchImportFile(MultipartFile file) {
        String fileOriginalFilename = file.getOriginalFilename();
        if (StringUtils.isNotBlank(fileOriginalFilename)) {
            String suffix = fileOriginalFilename.substring(fileOriginalFilename.lastIndexOf(".") + 1);
            if (StaticConstant.FILE_EXTENSION_XLSX.equalsIgnoreCase(suffix)) {
                // excel 导入林权数据
                // 保存文件
                String fileNewPath = CommonUtil.uploadFile(excelFolder, file);
                return batchImport(fileNewPath);
            } else if (StaticConstant.FILE_EXTENSION_ZIP.equalsIgnoreCase(suffix)
                    || StaticConstant.FILE_EXTENSION_MDB.equalsIgnoreCase(suffix)) {
                // zip .net解析
                // 保存文件
                String fileNewPath = CommonUtil.uploadFile(mdbOrZipFolder, file);
                return externalCall(fileNewPath);
            } else {
                return DataResult.fail("不支持的文件格式");
            }
        }
        return DataResult.fail("文件名错误");
    }

    @Override
    public DataResult changeData(BssForestRightInfoEntity bssForestRightInfo) {

//        if (StrUtil.isBlank(bssForestRightInfo.getGroundNo())) {
          /*  Map<String, String> map = new HashMap<>();
            map.put("groundNo", bssForestRightInfo.getGroundNo());
            map.put("id", bssForestRightInfo.getId());
            Long count = bssForestRightInfoMapper.findCountByGroundNo(map);
            if (count > 0) {
                return DataResult.fail("宗地号不能重复");
            }*/
//            return DataResult.fail("宗地号不能为空");
//        }

        String id = bssForestRightInfo.getId();
        BssForestRightInfoEntity dbEntity = this.getById(id);

        String dbFilePath = dbEntity.getFilePath();
        String filePath = bssForestRightInfo.getFilePath();

        boolean isChangeT = false;
        if (StrUtil.isNotBlank(dbFilePath)
                && StrUtil.isNotBlank(filePath)
                && !dbFilePath.equals(filePath)) {
            // 图形修改
            isChangeT = true;
        }

        if (StrUtil.isBlank(dbFilePath) && StrUtil.isNotBlank(filePath)) {
            // 图形新增
            isChangeT = true;
        }

        boolean b = this.updateById(bssForestRightInfo);

        // 图形解析
        if (isChangeT) {
            // 获取当前登录用户信息
            SysUserEntity sysUserEntity = (SysUserEntity) SecurityUtils.getSubject().getPrincipal();

            String uuid = UUID.randomUUID().toString();
            SysInteractiveEntity interactiveEntity = new SysInteractiveEntity();
            interactiveEntity.setId(getMaxId());
            interactiveEntity.setGuid(uuid);
            interactiveEntity.setStates(StaticConstant.HAS_NOT_STARTED);

            sysInteractiveService.save(interactiveEntity);
            // 调用外部程序
            CellOtherProgram exeUtil = new CellOtherProgram(
                    exePath,
                    bssForestRightInfo.getFilePath(),
                    sysUserEntity.getId(),
                    bssForestRightInfo.getId(),
                    sysUserEntity.getProvince(),
                    sysUserEntity.getCity(),
                    sysUserEntity.getCounty(),
                    uuid
            );
            exeUtil.send();
            DataResult result = getResDataByGuid(uuid);
            if (result.getCode() != 0) {
                return result;
            }
        }

        if (b) {
            // 保存操作记录
            BssAuditRecordsEntity auditRecordsEntity = new BssAuditRecordsEntity();
            auditRecordsEntity.setForestRightId(bssForestRightInfo.getId());
            if (bssForestRightInfo.getStatus().equals(ReviewStatusEnum.PENDING.getCode())) {
                auditRecordsEntity.setStatus(ReviewStatusEnum.PENDING.getCode());
            } else {
                auditRecordsEntity.setStatus(ReviewStatusEnum.SAVED.getCode());
            }
            bssAuditRecordsService.save(auditRecordsEntity);

//            // 加入队列
//            producers.send(JSONObject.toJSONString(bssForestRightInfo));

            return DataResult.success();
        }
        return DataResult.fail(BaseResponseCode.SYSTEM_BUSY.getMsg());
    }

    /**
     * 调用外部程序解析文件
     *
     * @param [fileNewPath]
     * @return com.otitan.webapp.framework.basepro.model.DataResult
     * @throws
     * @author jiachangsen
     * @date 2020/08/11 13:18
     */
    private DataResult externalCall(String fileNewPath) {
        String filePath = "";
        SysUserEntity sysUserEntity = (SysUserEntity) SecurityUtils.getSubject().getPrincipal();
        if (fileNewPath.endsWith(StaticConstant.FILE_EXTENSION_ZIP)) {
            String dir = fileNewPath.substring(0, fileNewPath.lastIndexOf(".")) + File.separator;

            try {
                ZipUtil.unZipFiles(fileNewPath, dir);
                File file = new File(dir);
                File[] list = file.listFiles();
                for (File f : list) {
                    boolean endsWith = f.getName().endsWith(StaticConstant.FILE_EXTENSION_SHP);
                    if (endsWith) {
                        filePath = f.getPath();
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            filePath = fileNewPath;
        }

        // 调用外部程序
        if (StrUtil.isNotBlank(filePath)) {
            String uuid = UUID.randomUUID().toString();
            SysInteractiveEntity interactiveEntity = new SysInteractiveEntity();
            interactiveEntity.setId(getMaxId());
            interactiveEntity.setGuid(uuid);
            interactiveEntity.setStates(StaticConstant.HAS_NOT_STARTED);
            sysInteractiveService.save(interactiveEntity);
            CellOtherProgram exeUtil = new CellOtherProgram(
                    exePath,
                    filePath,
                    sysUserEntity.getId(),
                    null,
                    sysUserEntity.getProvince(),
                    sysUserEntity.getCity(),
                    sysUserEntity.getCounty(),
                    uuid
            );
            exeUtil.batchSend();
            return getResDataByGuid(uuid);
        }
        return DataResult.fail(BaseResponseCode.SYSTEM_BUSY.getMsg());
    }

    /**
     * 批量导入林权证数据
     *
     * @param [fileNewPath]
     * @return com.otitan.webapp.framework.basepro.model.DataResult
     * @throws
     * @author jiachangsen
     * @date 2020/08/11 13:17
     */
    private DataResult batchImport(String fileNewPath) {

        String levels = "2,3,4";
        List<TreeDto> cityAndCounty = sysOrganizationService.getOrgByLevels(levels);
        Map<Integer, List<TreeDto>> collect = cityAndCounty.stream().
                collect(Collectors.groupingBy(TreeDto::getLevel));

        // 市级
        Map<String, String> cityMap = collect.get(2).stream().collect(Collectors.toMap(TreeDto::getId, TreeDto::getParentId));
        // 县级
        Map<String, String> countyMap = collect.get(3).stream().collect(Collectors.toMap(TreeDto::getName, TreeDto::getId));
        Map<String, String> countyParentIdMap = collect.get(3).stream().collect(Collectors.toMap(TreeDto::getId, TreeDto::getParentId));
        //乡,镇
        Map<String, String> viligeMap = collect.get(4).stream().collect(Collectors.toMap(k -> k.getName() + k.getParentId(), TreeDto::getId));

        // 宗地号唯一性判断检查Map
//        Set<String> allGroundNoSet = getAllGroundNo();

        // 读取 Excel
//        ExcelReader reader = new ExcelReader(cityMap, countyMap, countyParentIdMap, viligeMap, allGroundNoSet);
        ExcelReader reader = new ExcelReader(cityMap, countyMap, countyParentIdMap, viligeMap);
        Map<String, Object> res = reader.readExcel(fileNewPath);
        List<BssForestRightInfoEntity> data = (List<BssForestRightInfoEntity>) res.get("data");
        List<Row> errorData = (List<Row>) res.get("errorData");

        log.debug("【Excel批量导入】系统处理结果：{}",
                res.toString().replaceAll("\n", "").replaceAll("\t", ""));

        boolean hasSuccess = false;
        boolean hasError = false;

        if (CollUtil.isNotEmpty(data)) {
            hasSuccess = true;
            int batchSize = (data.size() / 200) + 1;
            this.saveBatch(data, batchSize);
        }

        if (CollUtil.isNotEmpty(errorData)) {
            hasError = true;
        }

        if (!hasSuccess && hasError) {
            // 没有成功任何一条
            return getImportExcelResData(errorData, true);
        }

        if (hasSuccess && hasError) {
            // 部分成功
            return getImportExcelResData(errorData, false);
        }
        if (!hasSuccess && !hasError) {
            // 模板为空
            return DataResult.fail("请检查导入文件是否为空？");
        }
        return DataResult.success();
    }

    /**
     * 获取数据库总所有宗地号
     *
     * @param []
     * @throws
     * @author jiachangsen
     * @date 2020/08/19 15:00
     */
    private Set<String> getAllGroundNo() {
        List<BssForestRightInfoEntity> allGroundNo = bssForestRightInfoMapper.getAllGroundNo();
        return allGroundNo.stream().map(BssForestRightInfoEntity::getGroundNo).collect(Collectors.toSet());
    }


    /**
     * 获取导入失败的返回结果
     *
     * @param [errorData, allError]
     * @return com.otitan.webapp.framework.basepro.model.DataResult
     * @throws
     * @author jiachangsen
     * @date 2020/08/19 14:38
     */
    private DataResult getImportExcelResData(List<Row> errorData, boolean allError) {
        // 读取错误模板
        Workbook sheets = MyExcelUtil.readExcelByFileName("【错误信息】贵州省林权登记信息入库数字化表.xlsx");
        // 写入错误信息
        MyExcelUtil.writeExcel(sheets, errorData);
        String dir = CommonUtil.mkdirs(errorFolder);
        String filePath = dir + File.separator + UUID.randomUUID() + ".xlsx";
        // 保存
        MyExcelUtil.keepExcel(sheets, filePath);

        Map<String, Object> resMap = new HashMap<>();
        resMap.put("code", -1);

        if (allError) {
            resMap.put("msg", "导入失败，是否下载错误信息？");
        } else {
            resMap.put("msg", "部分数据导入成功，是否下载错误信息？");
        }

        resMap.put("filePath", filePath);
        return DataResult.success(resMap);
    }


    /**
     * 设置统计数据
     *
     * @param [month, flag, totalNumAndTotalArea, licensedBook, licensedArea]
     * @return void
     * @throws
     * @author jiachangsen
     * @date 2020/08/12 09:30
     */
    private void setValues(String month,
                           boolean flag,
                           List<StatisticsPo> totalNumAndTotalArea,
                           List<BigDecimal> licensedBook,
                           List<BigDecimal> licensedArea) {
        BigDecimal value = BigDecimal.valueOf(0);
        for (StatisticsPo statisticsPo : totalNumAndTotalArea) {
            if (month.equals(statisticsPo.getMonths())) {
                flag = false;
                licensedBook.add(Optional.ofNullable(statisticsPo.getTotalNum()).orElse(value));
                if (licensedArea != null) {
                    licensedArea.add(Optional.ofNullable(statisticsPo.getTotalArea()).orElse(value));
                }
            }
        }
        if (flag) {
            licensedBook.add(value);
            if (licensedArea != null) {
                licensedArea.add(value);
            }
        }
    }

    /**
     * 根据年份获取统计开始时间和结束时间
     * 2020年 从8月开始，其他年份从1月开始
     *
     * @param year
     * @return java.util.Map
     * @throws
     * @author jiachangsen
     * @date 2020/08/09 10:28
     */
    private Map<String, Object> getStartDateAndEndDate(String year) {
        String startDateStr = "";
        String endDateStr = "";

        Integer nextYear = Integer.parseInt(year) + 1;
        if ("2020".equals(year)) {
            startDateStr = year + "0801000000";
            endDateStr = nextYear + "0101000000";
        } else {
            startDateStr = year + "0101000000";
            endDateStr = nextYear + "0101000000";
        }
        Map<String, Object> resMap = new HashMap<>();
        resMap.put("startDate", DateUtil.strToDate(startDateStr, DateUtil.YYYYMMDDHHMISS));
        resMap.put("endDate", DateUtil.strToDate(endDateStr, DateUtil.YYYYMMDDHHMISS));
        return resMap;
    }

    @Override
    public DataResult syncLqData(String uuid) {
        try {
            if ("otitan-admin".equals(uuid)) {
//                List<TreeDto> orgByLevels = sysOrganizationService.getOrgByLevels("5");
//                Map<String, String> map = orgByLevels.stream().collect(Collectors.toMap(TreeDto::getId, TreeDto::getName));
                bssForestRightInfoMapper.deleteData();
                Map<String, String> map = null;

                long current = 1;
                Page<BssForestRightInfoEntity> page = new Page<>(current, 500);
                Page<BssForestRightInfoEntity> entityPage = page.setRecords(bssForestRightInfoMapper.findSdeLqData(page));
                saveLqData(map, entityPage.getRecords());

                while (entityPage.hasNext()) {
                    page = new Page<>(++current, 500);
                    entityPage = page.setRecords(bssForestRightInfoMapper.findSdeLqData(page));
                    saveLqData(map, entityPage.getRecords());
                }
                return DataResult.success(current);
            } else {
                return DataResult.success("恶意入侵");
            }
        } catch (Exception e) {
            return DataResult.fail(e.getMessage());
        }
    }

    private void saveLqData(Map<String, String> map, List<BssForestRightInfoEntity> list) {

        if (CollUtil.isNotEmpty(list)) {
//            list.stream().forEach(item -> item.setVillage(map.get(item.getVillage())));
            boolean batch = this.saveBatch(list, 500);
        }
    }
}